<?php
/**
 * Auther: Joshua Conero
 * Date: 2017/5/13 0013 8:10
 * Email: brximl@163.com
 * Name:
 */

namespace app\api\controller;


use app\common\Aurora;
use app\common\controller\Api;
use app\common\model\Loger;
use hyang\Location;
use think\Db;
use think\Debug;

class Visit extends Api
{
    /**
     * ip 统计接口： 接受参数： limit 默认 30
     * @return \think\response\Json
     */
    public function getAreaByIp(){
        $limit = request()->param('limit');
        $limit = $limit? $limit:30;
        $visit = model('Visit');
        $data = $visit->where('ip not like \'192.168.%\' and ip <>\'127.0.0.1\'')
            ->where('annlyse_mk <>\'Y\' or annlyse_mk is null')
            ->field('ip,listid')
            ->limit($limit)
            ->select();
        $succssCtt = 0;$errLog = '';$msg='';
        Debug::remark('begin');
        try {
            foreach ($data as $v) {
                //println($v['ip'],Location::getLocation(Location::setIp($v['ip'])));
                // 已经执行，但annlyse_mk值更新失败的记录自动更新
                Db::execute('update `sys_visit` set `annlyse_mk`=\'Y\' where `ans_time` is not null and `province` is not null');
                $ansDt = Location::getLocation(Location::setIp($v['ip']));
                if ($ansDt['code'] == '0') { // 请求正确时
                    $succssCtt += 1;    // 正统统计
                    $ansDt = $ansDt['data'];
                    $visit->save([
                        'province' => $ansDt['region'],
                        'city' => $ansDt['city'],
                        'isp' => $ansDt['isp'],
                        'annlyse_mk' => 'Y',
                        'ans_data' => json_encode($ansDt),
                        'ans_time' => sysdate()
                    ], ['listid' => $v['listid']]);
                } else { // 数据请求失败
                    $visit->save([
                        'annlyse_mk' => 'Y',
                        'ans_data' => '{"remark":"数据请求失败"}',
                        'ans_time' => sysdate()
                    ], ['listid' => $v['listid']]);
                }
            }
        }catch (\Exception $e){
            $errLog = $e->getMessage();
            $msg = '，api请求过程中出现异常';
        }
        Debug::remark('end');
        $logmsg = "ip地址“".(request()->ip())."”为用户请求了该API,执行情况$succssCtt/".count($data);
        if($errLog) $logmsg .= ",错误异常信息：".$errLog;
        $logmsg .= "，运行耗时".Debug::getRangeTime('begin','end').'s';
        $logmsg .= ",运行内存".Debug::getRangeMem('begin','end').'kb';
        (new Loger())->write('ip_ans_area',$logmsg);
        return $this->FeekMsg("服务器已经响应".$msg,1);
    }

    /**
     * 获取到分布式数据，用于echart 构图
     * @return \think\response\Json
     */
    public function getDistributionCtt(){
//        $visit = model('Visit');
//        $data = $visit->where('province is not null')
//            ->field("replace(replace(province,'省',''),'市','') as province,
//    count(*) as ctt")
//            ->select();
        $data = db()->query("SELECT 
            replace(replace(province,'省',''),'市','') as province,
            count(*) as ctt FROM `sys_visit` WHERE province is not null GROUP by province");
        $retVal = [];
        // 特殊匹配
        $sMap = ['广西','西藏','新疆','内蒙古','宁夏','香港','澳门'];
        foreach ($data as $v){
            $province = $v['province'];
            foreach($sMap as $m){
                if(substr_count($province, $m) > 0){
                    $province = $m;
                    break;
                }
            }
            $retVal[] = [
                'name' => $province,
                'value' => $v['ctt'],
            ];
        }
        return json($retVal);
    }
    /**
     * 获取访客的地址信息
     * @return \think\response\Json
     */
    public function location(){
        $data = Aurora::location();
        return json($data);
    }

    /**
     * 地区分布统计: 城市、身份、国家(CT/P/CN) type, page = 1, num = 20
     */
    public function DistributionCtt(){
        $bind = [];
        $bind['v_type'] = $this->request->param('type', null);
        $bind['v_page'] = $this->request->param('page', 1);
        $bind['v_num'] = $this->request->param('num', 20);

        $year = $this->request->param('year', null);
        $month = $this->request->param('month', null);
        $vTime = [];$vFormat = [];
        if($year){
            $vTime[] = $year;
            $vFormat[] = '%Y';
        }
        if($month){
            $vTime[] = $month;
            $vFormat[] = '%m';
        }
        $bind['v_time'] = !empty($vTime)? implode('-', $vTime): null;
        $bind['v_format'] = !empty($vFormat)? implode('-', $vFormat): null;
        //$bind['v_page'] = $this->request->param('page', 1);
        //$bind['v_num'] = $this->request->param('num', 20);
        //println($bind);

        $rs = db()->query('call visit_rank(:v_type, :v_time, :v_format, :v_page, :v_num)', $bind);
        if(!empty($rs)){
            $rs = $rs[0];
        }
        return $this->FeekMsg($rs);
    }

    /**
     * 地区分布统计： echarts 数据获取
     */
    public function DistributionChart(){
        $type = $this->request->param('type');
        $year = $this->request->param('year');
        $month = $this->request->param('month');
        $vTime = [];$vFormat = [];$vFormatList = [];
        if($year){
            $vTime[] = $year;
            $vFormat[] = '%Y';
            $vFormatList[] = '%Y';
            $vFormatList[] = '%m';
        }
        if($month){
            $vTime[] = $month;
            $vFormat[] = '%m';
            $vFormatList[] = '%d';
        }
        $vTime = !empty($vTime)? implode('-', $vTime): null;
        $vFormat = !empty($vFormat)? implode('-', $vFormat): null;
        $vFormatList = !empty($vFormatList)? implode('-', $vFormatList): null;
        $bind = [
            'v_type' => $this->request->param('type'),
            'v_time' => $vTime,
            'v_format' => $vFormat
        ];
        $rs = db()->query('call visit_rank(:v_type, :v_time, :v_format, null, 5)', $bind);
        if($rs){
            $rs = $rs[0];
        }
        $option = [];
        // 内部函数
        $handlerFn = function($column) use ($rs, $vTime, $vFormat, $vFormatList, &$option){
            $legend = [];$series = [];$xAxis = [];
            $isFirst = true;
            foreach ($rs as $v){
                $legend[] = $v['name'];
                $wh = [
                    $column => $v['name'],
                    'annlyse_mk' => 'Y'
                ];
                $fmtList = 'date_format(mtime, \''.$vFormatList.'\')';
                $bind = [];
                if($vTime){
                    $bind['v_mtime'] = $vTime;
                }
                $data = db()->table('sys_visit')
                    ->field([$fmtList=>'name', 'count(*)'=>'value'])
                    ->where('date_format(mtime, \''.$vFormat.'\')=:v_mtime')
                    ->where($wh)
                    ->bind($bind)
                    ->group($fmtList)
                    ->order('mtime asc')
                    ->select()
                    ;
                /*
                debugOut(db()->table('sys_visit')
                    ->field([$fmt=>'name', 'count(*)'=>'value'])
                    ->where($wh)
                    ->group($fmt)
                    ->order('mtime asc')
                    ->select(false));
                */
                $seriesItem = [];
                $innerMap = [];
                foreach ($data as $row){
                    if($isFirst){
                        $xAxis[] = $row['name'];
                    }
                    $innerMap[$row['name']] = $row['value'];
                    if($isFirst){
                        $seriesItem[] = $row['value'];
                    }
                }
                if(!$isFirst){
                    foreach ($xAxis as $x){
                        $seriesItem[] = isset($innerMap[$x])? $innerMap[$x]: 0;
                    }
                }
                $isFirst = false;
                $series[] = [
                    'name' => $v['name'],
                    'type' => 'line',
                    'data' =>$seriesItem
                ];
            }
            $option['xAxis'] = ['data' => $xAxis];
            $option['legend'] = ['data' => $legend];
            $option['series'] = $series;
        };
        switch ($type){
            case 'CT':call_user_func($handlerFn, 'city'); break;
            case 'CN':call_user_func($handlerFn, 'country'); break;
            default:
                call_user_func($handlerFn, 'province');
        }
        return $this->FeekMsg($option);
    }
    /**
     * 日期可选范围
     */
    public function Range(){
        $type = $this->request->param('type', 'year');
        $retVal= [];
        switch ($type){
            case 'month':
                $year = $this->request->param('year');
                if($year){
                    $retVal = db()->table('sys_visit')
                        ->field(['date_format(mtime, \'%m\')'=>'value'])
                        ->where('date_format(mtime, \'%Y\')=:v_mtime')
                        ->bind(['v_mtime'=>$year])
                        ->group('date_format(mtime, \'%m\')')
                        ->order('mtime desc')
                        ->select()
                    ;
                }
                break;
            default:
                $retVal = db()->table('sys_visit')
                    ->field(['date_format(mtime, \'%Y\')'=>'value'])
                    ->group('date_format(mtime, \'%Y\')')
                    ->order('mtime desc')
                    ->select()
                    ;
        }
        return $this->FeekMsg($retVal);
    }
}